<template>
  <BasicModal
    title="测试窗口"
    :visible="visible"
    :mask="false"
    :width="680"
    :minHeight="300"
    :maskClosable="false"
    :canFullscreen="false"
    @cancel="handleCancel"
    cancelText="关闭"
    wrapClassName="test-modal"
  >
    <div class="test-window">
      <!-- 数据日志输出 -->
      <section class="output-container" v-if="output"  >
        <a-tabs size="small">
          <a-tab-pane :tab="table.name" v-for="table in tableMap" :key="table.id">
            <div :class="table.columns.length > 0 ? 'log-container' : ''" :style="{ height: hiddenLog ? '300px' : '' }" ref="tableContainer">
              <div class="row" :style="{ width: `${table.maxWidth}px` }">
                <span v-for="(column, colIndex) in table.columns" :key="'col_'+colIndex" class="table_body" :style="{ width: `${column.maxWidth}px` }">
                  {{ column.text }}
                </span>
              </div>
              <div v-for="(row, rowIndex) in table.rows" :key="'row_'+rowIndex" class="row" :style="{ width: `${table.maxWidth}px` }">
                <div v-for="(item, itemIndex) in row" :key="'item_'+itemIndex" class="table_body" :style="{ width: `${item.maxWidth}px` }">
                  <a-tooltip placement="bottomLeft" trigger="click">
                    <template #title>
                      <span>{{ item.text }}</span>
                    </template>
                    <span :color="item.color">{{ item.text }}</span>
                  </a-tooltip>
                </div>
              </div>
            </div>
          </a-tab-pane>
        </a-tabs>
      </section>
      <!-- 执行过程日志输出 -->
      <section class="log-container log-container-font" v-if="log" :style="{ height: hiddenTable ? '320px' : '100px' }" ref="logContainer">
        <div v-for="(log, logIndex) in messageNewLog" :key="'log_'+logIndex">
          <span
            v-for="(item, itemIndex) in log"
            :key="'logItem_'+ itemIndex"
            :style="{ color: item.color }"
            class="defaultOneLog"
          >
            <span v-if="item.tooltip">
              <a-tooltip placement="topLeft" trigger="click" overlayClassName="tooltip_class">
                <template #title>
                  <span>{{ item.text }}</span>
                </template>
                {{ item.text }}
              </a-tooltip>
            </span>
            <span v-else> {{ item.text }}</span>
          </span>
        </div>
      </section>
      <!-- 调试变量输出 -->
      <ul class="debug-container" v-if="debuger">
        <li><label>调试单元：</label>{{ cell.value }}</li>
        <li><label>调试参数：</label>{{ messageDebugs.key }}</li>
        <li>
          <label>调试值：</label>
          <vue-json-pretty v-if="isJsonMsg" :path="'res'" :deep="2" :data="messageDebugs ? messageDebugs.value : ''" />
          <span v-else>{{ messageDebugs ? messageDebugs.value : '' }}</span>
        </li>
      </ul>
    </div>

    <template #footer>
      <a-button size="small" type="primary" @click="handleCancel">关闭</a-button>
      <a-button size="small" @click="handleOutput">显示/隐藏输出</a-button>
      <a-button size="small" @click="handleLog">显示/隐藏日志</a-button>
      <a-button size="small" @click="handleConnect">{{ connectStatus }}</a-button>
      <a-input size="small" placeholder="输入关键字过滤日志" class="searchInput" v-model:value="keyLogWord" />
    </template>
  </BasicModal>
</template>
<script setup>
  import { ref, reactive, watch, computed, nextTick } from 'vue';
  import { useGlobSetting } from '/@/hooks/setting';
  import { getToken } from '/@/utils/auth';
  import { BasicModal } from '/@/components/Modal';
  import { RpaEditor } from '../utils/render/index';
  import VueJsonPretty from 'vue-json-pretty';
  const props = defineProps({
    cell: { type: Object },
    editor: { type: RpaEditor },
  });
  const emit = defineEmits(['handleShowBtn', 'debugMessage']);
  const glob = useGlobSetting();
  const visible = ref(false);
  const websock = ref();
  const tableContainer = ref();
  const logContainer = ref(null);
  const debugs = ref('');
  const output = ref(true);
  const log = ref(false);
  //输出表Map
  const tableMap = reactive([]);
  const messageLog = ref([]);
  const hiddenTable = ref(false);
  const hiddenLog = ref(false);
  const connectStatus = ref('停止');
  const keyLogWord = ref('');
  const messageTable = reactive([]);
  const nodeIds = reactive([]);
  const result = ref(false);
  const messageDebugs = ref('');
  const debuger = ref(false);

  const isJsonMsg = computed(() => {
    return Array.isArray(messageDebugs.value.value) || typeof messageDebugs.value.value === 'object';
  });

  function testAction(debug) {
    visible.value = true;
    debugs.value = debug;
    //清空输出表
    tableMap.splice(0, tableMap.length);
    //初始化WEBSOCKET
    initWebSocket();
  }

  watch(
    () => messageLog.value,
    () => {
      nextTick(() => {
        if (log.value && logContainer.value) {
          logContainer.value.scrollTop = logContainer.value.scrollHeight;
        }
      });
    },
    { deep: true }
  );

  watch(
    () => tableMap,
    () => {
      nextTick(() => {
        if (tableContainer.value) {
          tableContainer.value.forEach((item)=>{
            item.scrollTop = item.scrollHeight;
          })
        }
      });
    },
    { deep: true }
  );

  const messageNewLog = computed(() => {
    if (!keyLogWord.value) {
      return messageLog.value;
    } else {
      return messageLog.value.filter((item) => {
        return item.some((v) => {
          return String(v.text).indexOf(keyLogWord.value) > -1;
        });
      });
    }
  });

  function initWebSocket() {
    const token = getToken() || '';
    let url = glob.domainUrl?.replace('https://', 'wss://').replace('http://', 'ws://') + '/ws-rpa/ws';
    websock.value = new WebSocket(url,[token]);
    websock.value.onopen = websocketOnopen;
    websock.value.onerror = websocketOnerror;
    websock.value.onmessage = websocketOnmessage;
    websock.value.onclose = websocketOnclose;
  }
  function websocketOnopen() {
    if (websock.value.readyState === 1) {
      websock.value.send(
        JSON.stringify({
          type: 'spider-flow',
          eventType: debugs.value === 'true' ? 'debug' : 'test',
          message: props.editor.getGraph().outPutXml(),
        })
      );
    }
  }
  function websocketOnmessage(e) {
    const event = JSON.parse(e.data);
    const { eventType, message } = event;
    const colors = {
      array: '#2a00ff',
      object: '#2a00ff',
      boolean: '#600100',
      number: '#000E59',
    };
    if (eventType === 'finish') {
      connectStatus.value = '重新开始';
      emit('handleShowBtn');
    } else if (eventType === 'output') {
      output.value = true;
      const { nodeId, outputNames, values } = message;
      let tableId = 'output-' + nodeId;
      let outputTitle = '输出-' + tableId;
      let cell = props.editor.getGraph().getCell(nodeId);
      if (cell) {
        outputTitle = cell.value;
      }
      // 计算列宽
      const tableColumnTotalWidth = 576;
      const tableColumnIndexWidth = 60;
      const tableColumnMaxWidth = 192;
      const tableColumnMinWidth = 120;
      let tableColumnWidth = tableColumnMaxWidth;
      if(outputNames.length == 1){
        tableColumnWidth = tableColumnTotalWidth;
      }else  if(outputNames.length == 2){
        tableColumnWidth = tableColumnTotalWidth / 2;
      }else if(outputNames.length > 0){
        tableColumnWidth = tableColumnTotalWidth / outputNames.length;
        if(tableColumnWidth < tableColumnMinWidth){
          tableColumnWidth = tableColumnMinWidth;
        }else if(tableColumnWidth > tableColumnMaxWidth){
          tableColumnWidth = tableColumnMaxWidth;
        }
      }
      // 检测表,并初始化列头
      let table = tableMap.find((item) => item.id == tableId);
      if (!table) {
        tableMap.push(
          table = {
            index: 0,
            id: tableId,
            name: outputTitle,
            maxWidth: 0,
            columns: [],
            rows: [],
          }
        );
        let texts = [
          {
            text: '序号',
            maxWidth: tableColumnIndexWidth,
          },
        ];
        
        outputNames.forEach((item, index) => {
          texts.push({
            text: item,
            maxWidth: tableColumnWidth,
          });
        });
        table.columns = texts;

        let tableWidth = 0;
        table.columns.forEach((item, index) => {
          tableWidth += item.maxWidth;
        });
        table.maxWidth = tableWidth;
      }
      // 添加行号
      let texts = [
        {
          text: ++table.index,
          maxWidth: tableColumnIndexWidth,
          color: 'black',
        },
      ];
      // 添加行数据
      outputNames.forEach((item, index) => {
        let displayText = values[index];
        let variableType = 'string';
        if (Array.isArray(displayText)) {
          variableType = 'array';
          displayText = JSON.stringify(displayText);
        } else {
          variableType = typeof displayText;
          if (variableType == 'object') {
            displayText = JSON.stringify(displayText);
          }
        }
        texts.push({
          text: displayText,
          maxWidth: tableColumnWidth,
          color: colors[variableType] || 'black',
        });
      });
      table.rows.push(texts);
    } else if (eventType === 'log') {
      log.value = true;
      const texts = [];
      const defaultColor = message.level === 'error' ? 'red' : '';
      texts.push({
        text: message.level,
        color: defaultColor,
        tooltip: false,
      });
      texts.push({
        text: event.timestamp,
        color: defaultColor,
        tooltip: false,
      });
      let temp = message.message.split('{}');
      message.variables = message.variables || [];
      for (var j = 0, leng = temp.length; j < leng; j++) {
        if (temp[j] !== '') {
          texts.push({
            text: temp[j],
            color: defaultColor,
            tooltip: false,
          });
        }
        let object = message.variables[j];
        if (object !== undefined) {
          let variableType = '';
          let displayLogText = object;
          if (Array.isArray(object)) {
            variableType = 'array';
            displayLogText = JSON.stringify(displayLogText);
          } else {
            variableType = typeof object;
            if (variableType === 'object') {
              displayLogText = JSON.stringify(displayLogText);
            }
          }
          texts.push({
            text: displayLogText,
            color: colors[variableType] || '#025900',
            tooltip: true,
          });
        }
      }
      messageLog.value.push(texts);
    } else if (eventType === 'debug') {
      props.editor.getGraph().setCellSelected(props.editor.getGraph().getCell(message.nodeId));
      emit('debugMessage', message);
      debuger.value = true;
      messageDebugs.value = message;
    }
  }
  function websocketOnerror(e) {
    console.log(' WebSocket连接发生错误 ');
  }
  function websocketOnclose(e) {
    console.log('connection closed (' + e + ')');
  }
  function handleCancel() {
    visible.value = false;
    connectStatus.value = '停止';
    emit('handleShowBtn', false);
    output.value = false;
    log.value = false;
    debuger.value = false;
    hiddenTable.value = false;
    hiddenLog.value = false;
    emit('debugMessage', {});
    tableMap.splice(0, tableMap.length);
    messageTable.splice(0, messageTable.length);
    messageLog.value = [];
    keyLogWord.value = '';
    messageDebugs.value = '';
    try {
      websock.value.close();
    } catch {
      websock.value = null;
    }
  }
  function handleOutput() {
    output.value = !output.value;
    hiddenTable.value = !hiddenTable.value;
  }
  function handleLog() {
    log.value = !log.value;
    hiddenLog.value = !hiddenLog.value;
  }
  function handleConnect() {
    if (connectStatus.value === '停止') {
      websock.value.send(
        JSON.stringify({
          type: 'spider-flow',
          eventType: 'stop',
        })
      );
      debuger.value = false;
      messageDebugs.value = '';
      emit('debugMessage', {});
    } else {
      tableMap.splice(0, tableMap.length);
      messageTable.splice(0, messageTable.length);
      websock.value.send(
        JSON.stringify({
          type: 'spider-flow',
          eventType: debugs.value === 'true' ? 'debug' : 'test',
          message: props.editor.getGraph().outPutXml(),
        })
      );
      connectStatus.value = '停止';
    }
  }
  function handleNext() {
    websock.value.send(
      JSON.stringify({
        type: 'spider-flow',
        eventType: 'resume',
      })
    );
  }
  function handleStop() {
    websock.value.send(
      JSON.stringify({
        type: 'spider-flow',
        eventType: 'stop',
      })
    );
  }
  function handleClose() {
    handleCancel();
  }
  defineExpose({
    handleNext,
    handleStop,
    testAction,
    handleClose,
  });
</script>
<style lang="less">
  /* 测试、debuger模态框 ------ */
  .test-modal {
    pointer-events: none;
    user-select: none;
    .ant-modal {
      top: 150px;
      right: -400px;
    }
    ::-webkit-scrollbar {
      width: 0px;
      height: 0px;
      background-color: #f5f5f5;
    }
    /* 主题内容区 */
    // .ant-modal-body {
    //   padding: 0px 5px;
    .output-container {
      margin-bottom: 5px;

      ::-webkit-scrollbar {
        width: 5px;
        height: 5px;
        background-color: #f5f5f5;
      }
    }

    .output-title {
      width: 60px;
      padding: 5px 0;
      font-size: 14px;
      text-align: center;
      // border-bottom: solid 1px #1890FF;
    }

    .test-window {
      height: 340px;
      padding: 0px;
      overflow: hidden;
      position: relative;
      overflow: auto;
    }

    .row {
      overflow-x: auto;
      display: flex;
      align-items: center;
      border-bottom: solid 1px #ccc;
    }

    .table_body {
      height: 20px;
      line-height: 20px;
      display: inline-block;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      color: #000;
      padding: 0 10px;
      border-right: solid 1px #ccc;
    }

    .log-container {
      height: 200px;
      overflow: auto;
      font-weight: bold;
      font-size: 13px;
      font-family: Consolas;
      border: solid 1px #ccc;
      padding: 5px;
      margin-top: -16px;
    }

    .log-container-font {
      font-size: 14px;
      margin-top: 0px;
    }

    .defaultOneLog {
      margin-right: 10px;
      max-width: 43%;
      display: inline-block;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      color: #000;
    }
    // }

    .debug-container {
      padding: 5px;
      font-weight: bold;
      font-family: Consolas;
      font-size: 14px;
      color: #000;
      border: solid 1px #ccc;
      white-space: nowrap;
      margin: 5px 0;
      li {
        list-style: none;
        margin-bottom: 5px;
        label {
          width: 70px;
        }
      }
      li:nth-child(3) {
        display: flex;
        margin: 0;
        span {
          white-space: pre-wrap;
          word-break: break-all;
        }
      }
    }
  }
  .searchInput {
    width: 180px;
    margin-left: 10px;
  }
  .tooltip_class {
    max-width: 450px;
  }
</style>
